﻿// Copyright (C) 2012 Jeff Tanner <jeff00seattle@gmail.com>
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Security;

using WebSlideProjector.Configuration;
using WebSlideProjector.Extensions;

namespace WebSlideProjector
{
    public partial class Login : System.Web.UI.Page
    {
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Event handler. Called by Page for load events. </summary>
        ///
        /// <param name="sender">   Source of the event. </param>
        /// <param name="e">        Event information. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        protected void Page_Load(object sender, EventArgs e)
        {
            Session["User"] = null;

            if (!AppSettings.SlideCarouselLoginMode)
            {
                Response.Redirect("~/Default.aspx");
            }

            if (!Page.IsPostBack)
            {
                this.Title = String.Format("{0} - {1}: Slide Carousel Login", AppSettings.AssemblyName, AppSettings.AssemblyVersion);

                this.tryAutoLogin();
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Event handler. Called by Login1 for authenticate events. </summary>
        ///
        /// <param name="sender">   Source of the event. </param>
        /// <param name="e">        Event information. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        protected void Login1_Authenticate(object sender, AuthenticateEventArgs e)
        {
            string userName = this.Login1.UserName;
            string pwd = this.Login1.Password;

            if (FormsAuthentication.Authenticate(name: userName, password: pwd))
            {
                this.generateAuthenticationCookie(userName: userName, expirationInMinutes: AppSettings.CookieExpireInMinutes);
                Session["User"] = new UserBLL { UserName = userName, Authorized = true };
                FormsAuthentication.RedirectFromLoginPage(userName, true);
            }
            else
            {
                Response.Write("Invalid login details. Please try again.");
            }
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Generates an authentication cookie. </summary>
        ///
        /// <param name="expirationInMinutes">  The expiration in minutes. </param>
        /// <param name="userName">             Name of the user. </param>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        private void generateAuthenticationCookie(int expirationInMinutes, string userName)
        {
            DateTime cookieExpiration = DateTime.Now.AddMinutes(expirationInMinutes);
            var authenticationTicket =
                new FormsAuthenticationTicket(
                    2,
                    userName,
                    DateTime.Now,
                    cookieExpiration,
                    true,
                    string.Empty,
                    FormsAuthentication.FormsCookiePath
                    );
            // ticket must be encrypted         
            string encryptedTicket = FormsAuthentication.Encrypt(authenticationTicket);
            // create cookie to contain encrypted auth ticket         
            var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
            authCookie.Expires = authenticationTicket.Expiration;
            authCookie.Path = FormsAuthentication.FormsCookiePath;
            // clear out existing cookie for good measure (probably overkill) then add         
            HttpContext.Current.Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
            HttpContext.Current.Response.Cookies.Add(authCookie);
        }

        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>   Try automatic login. </summary>
        ////////////////////////////////////////////////////////////////////////////////////////////////////

        private bool tryAutoLogin()
        {
            HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(FormsAuthentication.FormsCookieName);
            if (cookie != null)
            {
                FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
                if (ticket != null)
                {
                    if (ticket.Name.Length > 0)
                    {
                        try
                        {
                            string userName = ticket.Name;
                            Session["User"] = new UserBLL { UserName = userName, Authorized = true };

                            FormsAuthentication.RedirectFromLoginPage(userName, true);
                            return true;
                        }
                        catch (Exception ex)
                        {
                            // don't do anything for now                      
                        }
                    }
                }
            }

            return false;
        }
    }
}